﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using vJine.Core.IoC;
using System.Text.RegularExpressions;
using System.Data.Common;
using System.IO;
using System.Reflection;
using System.Data;
using System.Reflection.Emit;

namespace vJine.Core.ORM {
    public partial class OrmConfig {
        #region Init
        /// <summary>
        /// 初始化配置类
        /// </summary>
        /// <returns>ORM配置类</returns>
        public OrmConfig Init() {

            this.Init_Adapters();

            this.Init_Connections();

            this.Init_TypeMap();

            this.Init_EntityMap();

            return this;
        }

        static string[] DEFAULT_ADAPTERS =
                new string[] { 
                    /*Name, Pattern, AdapterType, ProviderName, ConnectionString*/
                    "SQLite", "^SQLite", Class<vJine.Core.ORM.Adapters.SQLite>.AssemblyQualifiedName, "System.Data.SQLite", 
                    "Data Source=.\vjine_sqlite_data.db;Version=3;Pooling=True;Max Pool Size=100;"

                    ,"ACCESS", "^ACCESS", Class<vJine.Core.ORM.Adapters.ACCESS>.AssemblyQualifiedName, "System.Data.OleDb", 
                    "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=.\vjine_access_data.accdb"

                    ,"MySQL", "^MySQL", Class<vJine.Core.ORM.Adapters.MySQL>.AssemblyQualifiedName, "MySql.Data.MySqlClient",
                    "server=127.0.0.1;charset=utf8;User Id=root;Password=*******;database=test;Persist Security Info=True"

                    ,"PGSQL", "(^PGSQL)|(Npgsql)", Class<vJine.Core.ORM.Adapters.PGSQL>.AssemblyQualifiedName, "Npgsql", 
                    "Server=127.0.0.1;Port=5432;Userid=postgres;database=postgres;password=*******;Protocol=3;SSL=false;Pooling=true;MinPoolSize=1;MaxPoolSize=20;Encoding=UNICODE;Timeout=60;SslMode=Disable"

                    ,"MSSQL", "(^MSSQL)|(SqlClient)", Class<vJine.Core.ORM.Adapters.MSSQL>.AssemblyQualifiedName, "System.Data.SqlClient",
                    "Data Source=127.0.0.1;Initial Catalog=test;Persist Security Info=True;User ID=sa;pwd=*******"

                    ,"Oracle", "^Oracle", Class<vJine.Core.ORM.Adapters.Oracle>.AssemblyQualifiedName, "Oracle.DataAccess.Client",
                    "DATA SOURCE=127.0.0.1;PERSIST SECURITY INFO=True;USER ID=SYSTEM;Password=*******"
                };

        /// <summary>
        /// 初始化数据库适配器
        /// </summary>
        void Init_Adapters() {
            if (this.Adapters == null) {
                this.Adapters = new AdapterCollection();
            }
            
            for (int i = 0, len = OrmConfig.DEFAULT_ADAPTERS.Length; i < len; i += 5) {
                string _name = OrmConfig.DEFAULT_ADAPTERS[i];

                if(!this.Adapters.ContainsKey(_name)) {
                    string _pattern = OrmConfig.DEFAULT_ADAPTERS[i + 1];
                    ;
                    Type _type = Reflect.GetType(OrmConfig.DEFAULT_ADAPTERS[i + 2], false);
                    string _providerName = OrmConfig.DEFAULT_ADAPTERS[i + 3];
                    string _connString = OrmConfig.DEFAULT_ADAPTERS[i + 4];

                    Adapter adapter_i = new Adapter() {
                        name = _name, pattern = _pattern, type = _type,
                        providerName = _providerName, connectionString = _connString
                    };
                    this.Adapters.Add(_name, adapter_i);
                }
            }
        }

        /// <summary>
        /// 初始化数据库连接
        /// </summary>
        void Init_Connections() {
            if (this.Connections == null) {
                this.Connections = new ConnectionCollection();
            }

            ConnectionStringSettingsCollection cssc = ConfigurationManager.ConnectionStrings;
            for (int i = 0, len = cssc.Count; i < len; i++) {
                ConnectionStringSettings css_i = cssc[i];

                if (string.IsNullOrEmpty(css_i.Name)
                    || string.IsNullOrEmpty(css_i.ProviderName) && string.IsNullOrEmpty(css_i.ConnectionString)) {
                    continue;
                }

                if(this.Connections[css_i.Name] == null) {
                    db db_i = new db() {
                        name = css_i.Name, providerName = css_i.ProviderName, connectionString = css_i.ConnectionString
                    };
                    this.Connections.Add(db_i);
                }
            }

            for(int i = 0, len = OrmConfig.DEFAULT_ADAPTERS.Length; i < len; i += 5) {
                string _name = OrmConfig.DEFAULT_ADAPTERS[i];

                if(this.Connections[_name] == null) {
                    string _providerName = OrmConfig.DEFAULT_ADAPTERS[i + 3];
                    string _connString = OrmConfig.DEFAULT_ADAPTERS[i + 4];

                    db db_i = new db() {
                        name = _name, adapter = _name, providerName = _providerName, connectionString = _connString
                    };
                    this.Connections.Add(db_i);
                }
            }

            for (int i = 0, len = this.Connections.Count; i < len; i++) {
                db db_i = this.Connections[i];
                this.get_Adapter(db_i);
                this.get_Factory(db_i);

                if(!string.IsNullOrEmpty(db_i.connectionString)) {
                    db_i.connectionString =
                        string.Format(db_i.connectionString,
                        db_i.host, db_i.port, db_i.user, db_i.password, db_i.catalog);
                }
            }
        }

        /// <summary>
        /// 初始化全局类型映射
        /// </summary>
        void Init_TypeMap() {
            if(this.TypeMaps == null) {
                this.TypeMaps = new TypeMapCollection();
            }

            for (int i = 0, len = this.TypeMaps.Count; i < len; i++) {
                Map map_i = this.TypeMaps[i];
                if(!map_i.active) {
                    continue;
                }

                string adapter_name = string.IsNullOrEmpty(map_i.adapter) ? this.TypeMaps.adapter : map_i.adapter;
                if(string.IsNullOrEmpty(adapter_name)) {
                    continue;
                }
                
                Type db_adapter_type = this.Adapters[adapter_name];
                if(db_adapter_type == null) {
                    continue;
                }

                if(!this.TypeMapIndex.ContainsKey(db_adapter_type)) {
                    this.TypeMapIndex.Add(db_adapter_type, new Dictionary<Type, Map>());
                }
                Dictionary<Type, Map> dbMapIndex = this.TypeMapIndex[db_adapter_type];

                Type field_type = map_i.type;
                if (!dbMapIndex.ContainsKey(field_type)) {
                    dbMapIndex.Add(field_type, map_i);
                } else {
                    Map map = dbMapIndex[field_type];
                }
            }
        }

        //初始化实体类型映射
        void Init_EntityMap() {
            if(this.EntityMaps == null) {
                this.EntityMaps = new EntityCollection();
            }

            for (int i = 0, len_i = this.EntityMaps.Count; i < len_i; i++) {
                Entity schema_i = this.EntityMaps[i];
                if(
                    schema_i == null || schema_i.type == null || schema_i.Count == 0
                    || !schema_i.active
                    ) {
                    continue;
                }

                string adapter_name = 
                    string.IsNullOrEmpty(schema_i.adapter) ? this.EntityMaps.adapter : schema_i.adapter;
                if(string.IsNullOrEmpty(adapter_name)) {
                    continue;
                }

                //
                Type adapter_type = this.Adapters[adapter_name];
                if (adapter_type == null) {
                    continue;
                }
                if (!this.SchemaMapIndex.ContainsKey(adapter_type)) {
                    this.SchemaMapIndex.Add(adapter_type, new Dictionary<Type, Dictionary<string, Map>>());
                }
                Dictionary<Type, Dictionary<string, Map>> adapterIndex = this.SchemaMapIndex[adapter_type];
                
                //
                if(!adapterIndex.ContainsKey(schema_i.type)) {
                    adapterIndex.Add(schema_i.type, new Dictionary<string, Map>());
                }
                Dictionary<string, Map> classIndex = adapterIndex[schema_i.type];
                for (int j = 0, len_j = schema_i.Count; j < len_j; j++) {
                    Map map_j = schema_i[j];
                    if(map_j == null || string.IsNullOrEmpty(map_j.Name) || !map_j.active) {
                        continue;
                    }

                    if (classIndex.ContainsKey(map_j.Name)) {
                        classIndex[map_j.Name] = map_j;
                    } else {
                        classIndex.Add(map_j.Name, map_j);
                    }
                }
            }
        }

        #endregion Init
        void get_Adapter(OrmConfig.db db_config) {

            Adapter adapter = this.Adapters[db_config.adapter];
            if(adapter == null) {
                adapter =
                    this.get_Adapter_by_pattern(db_config.name, db_config.providerName);
            }

            if(adapter == null) {
                db_config.get_Adapter = () => {
                    throw new OrmException("数据库[{0}]未找到对应的适配器", db_config.name);
                };
            } else {
                if(string.IsNullOrEmpty(db_config.providerName) && string.IsNullOrEmpty(db_config.type)) {
                    db_config.providerName = adapter.providerName;
                }
                if(string.IsNullOrEmpty(db_config.connectionString)) {
                    db_config.connectionString = adapter.connectionString;
                }

                db_config.get_Adapter = () => {
                    return Class.Create(adapter) as IDbAdapter;
                };
            }
        }

        Adapter get_Adapter_by_pattern(params string[] db_hints) {
            foreach(KeyValuePair<string, Adapter> kv in this.Adapters) {
                Adapter adapter = kv.Value;
                for(int i = 0, len = db_hints.Length; i < len; i++) {
                    string db_hint = db_hints[i];
                    if(string.IsNullOrEmpty(db_hint)) {
                        continue;
                    }

                    if(!Regex.IsMatch(db_hint, adapter.pattern, RegexOptions.IgnoreCase)) {
                        continue;
                    }

                    Type adapter_type = adapter.type;
                    if(adapter_type == null) {
                        return null;
                    } else if(!adapter_type.IsSubclassOf(typeof(IDbAdapter))) {
                        return null;
                    } else {
                        return adapter;
                    }
                }
            }

            return null;
        }

        void get_Factory(OrmConfig.db db_config) {
            try {
                Call<DbProviderFactory, Type> get_factory = (Type T_factory) => {
                    FieldInfo fldInstance =
                        T_factory.GetField("Instance", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public);
                    if(fldInstance != null && fldInstance.FieldType.IsSubclassOf(typeof(DbProviderFactory))) {
                        object value = fldInstance.GetValue(null);
                        if(value != null) {
                            return value as DbProviderFactory;
                        } else {
                            return null;
                        }
                    } else {
                        return null;
                    }
                };

                DbProviderFactory db_factory = null;

                if(!string.IsNullOrEmpty(db_config.providerName)) {
                    if(this.debug) {
                        System.Console.WriteLine("======***=======");
                        System.Console.WriteLine("==" + db_config.providerName);
                        System.Console.WriteLine("==" + db_config.type);
                    }

                    db_factory = DbProviderFactories.GetFactory(db_config.providerName);
                    if(db_factory == null) {
                        db_config.get_Factory = () => {
                            throw new OrmException(
                            "数据库[{0}], 获取Factory错误【Provider未识别】, providerName[{1}]", db_config.name, db_config.providerName);
                        };
                    } else {
                        db_config.get_Factory = () => {
                            return db_factory;
                        };
                    }
                } else if(!string.IsNullOrEmpty(db_config.type)) {
                    Type T_factory = null;

                    if(!string.IsNullOrEmpty(db_config.bin_path)) {
                        if(!File.Exists(db_config.bin_path)) {
                            db_config.get_Factory = () => {
                                throw new OrmException(
                                "数据库[{0}], 获取Factory错误【未找到文件】, bin_path[{1}]", db_config.bin_path);
                            };
                        } else {
                            Assembly asmProvider =
                                Assembly.Load(File.ReadAllBytes(db_config.bin_path));
                            T_factory = asmProvider.GetType(db_config.type, false);
                            if(T_factory == null) {
                                db_config.get_Factory = () => {
                                    throw new OrmException(
                                    "数据库[{0}], , 获取Factory错误【未找到类】, bin_path[{1}], type[{2}]", db_config.name, db_config.bin_path, db_config.type);
                                };
                            } else {
                                db_factory = get_factory(T_factory);
                                if(db_factory == null) {
                                    db_config.get_Factory = () => {
                                        throw new OrmException(
                                        "数据库[{0}], 获取Factory错误【类型未找到DbProviderFactory】, bin_path[{1}], type[{2}]", db_config.name, db_config.bin_path, db_config.type);
                                    };
                                } else {
                                    db_config.get_Factory = () => {
                                        return db_factory;
                                    };
                                }
                            }
                        }
                    } else {
                        T_factory = Reflect.GetType(db_config.type);
                        if(T_factory == null) {
                            db_config.get_Factory = () => {
                                throw new OrmException(
                                "数据库[{0}], , 获取Factory错误【未找到类型】, type[{1}]", db_config.name, db_config.type);
                            };
                        } else {
                            db_factory = get_factory(T_factory);
                            if(db_factory == null) {
                                db_config.get_Factory = () => {
                                    throw new OrmException(
                                    "数据库[{0}], 获取Factory错误【类型未找到DbProviderFactory】, type[{1}]", db_config.name, db_config.type);
                                };
                            } else {
                                db_config.get_Factory = () => {
                                    return db_factory;
                                };
                            }
                        }
                    }
                } else {
                    db_config.get_Factory = () => {
                        throw new OrmException(
                        "数据库[{0}], Factory配置错误[0]，需要配置providerName或type、bin_path", db_config.name);
                    };
                }
            } catch(Exception ex) {
                db_config.get_Factory = () => {
                    throw new OrmException(
                        "数据库[{0}], 获取Factory错误, Ex:{1}", db_config.name, ex);
                };
            }
        }
        /// <summary>
        /// 获取指定属性的全局类型映射（由用户配置文件TypeMaps指定）
        /// </summary>
        /// <typeparam name="Tadapter">适配器类型</typeparam>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="p">属性</param>
        /// <returns>类型映射</returns>
        public Map getGlobalMap<Tadapter, Tentity>(Class<Tentity>.Property p) where Tadapter : IDbAdapter {

            Type T_adapter = typeof(Tadapter);

            Dictionary<Type, Dictionary<Type, Map>> typeMapIndex = this.TypeMapIndex;
            if (!typeMapIndex.ContainsKey(T_adapter)) {
                return null;
            } else {
                Dictionary<Type, Map> baseMapIndex = typeMapIndex[T_adapter];
                if (!baseMapIndex.ContainsKey(p.pType)) {
                    return null;
                } else {
                    return baseMapIndex[p.pType];
                }
            }
        }
        /// <summary>
        /// 获取指定属性的实体类型映射（由用户配置文件EntityMaps指定）
        /// </summary>
        /// <typeparam name="Tadapter">适配器类型</typeparam>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="p">属性</param>
        /// <returns>类型映射</returns>
        public Map getEntityMap<Tadapter, Tentity>(Class<Tentity>.Property p) where Tadapter : IDbAdapter {

            Type T_adapter = typeof(Tadapter);
            Type T_entity = typeof(Tentity);

            Dictionary<Type, Dictionary<Type, Dictionary<string, Map>>> dbMapIndex = this.SchemaMapIndex;
            if (!dbMapIndex.ContainsKey(T_adapter)) {
                return null;
            } else {
                Dictionary<Type, Dictionary<string, Map>> schemaMapIndex = dbMapIndex[T_adapter];
                if (!schemaMapIndex.ContainsKey(T_entity)) {
                    return null;
                } else {
                    Dictionary<string, Map> tbMapIndex = schemaMapIndex[T_entity];
                    if (!tbMapIndex.ContainsKey(p.Name)) {
                        return null;
                    } else {
                        return tbMapIndex[p.Name];
                    }
                }
            }
        }
    }
    /// <summary>
    /// 泛型数据库配置类
    /// </summary>
    /// <typeparam name="Tadapter">适配器类型</typeparam>
    public class OrmConfig<Tadapter>
            where Tadapter : IDbAdapter<Tadapter> {
        /// <summary>
        /// 实例化泛型数据库配置类
        /// </summary>
        public OrmConfig() {
        }

        static Dictionary<Type, OrmConfig.Map> TypeMaps = new Dictionary<Type, OrmConfig.Map>();
        /// <summary>
        /// 初始化数据库适配器默认类型映射
        /// </summary>
        /// <param name="type">属性类型</param>
        /// <param name="SQL_TYPE">数据库类型</param>
        /// <param name="dbType">命令参数类型</param>
        public static void InitDefaultMap(Type type, string SQL_TYPE, DbType dbType) {
            OrmConfig<Tadapter>.InitDefaultMap(type, SQL_TYPE, dbType, null);
        }
        /// <summary>
        /// 初始化数据库适配器默认类型映射
        /// </summary>
        /// <param name="type">属性类型</param>
        /// <param name="SQL_TYPE">数据库类型</param>
        /// <param name="dbType">命令参数类型</param>
        /// <param name="Conv">转换器类型</param>
        public static void InitDefaultMap(Type type, string SQL_TYPE, DbType dbType, Type Conv) {
            OrmConfig.Map map = new OrmConfig.Map() { SQL_TYPE = SQL_TYPE, DbType = dbType, Conv = Conv };
            if(!OrmConfig<Tadapter>.TypeMaps.ContainsKey(type)) {
                OrmConfig<Tadapter>.TypeMaps.Add(type, map);
            } else {
                OrmConfig<Tadapter>.TypeMaps[type] = map;
            }
        }
        /// <summary>
        /// 获取数据库适配器默认类型映射（在数据库适配器代码中指定）
        /// </summary>
        /// <param name="type">属性类型</param>
        /// <returns>类型映射</returns>
        public static OrmConfig.Map getDefaultMap(Type type) {
            if(!OrmConfig<Tadapter>.TypeMaps.ContainsKey(type)) {
                return null;
            }

            return OrmConfig<Tadapter>.TypeMaps[type];
        }
    }
    /// <summary>
    /// 泛型数据库配置类
    /// </summary>
    /// <typeparam name="Tadapter">适配器类型</typeparam>
    /// <typeparam name="Tentity">实体类型</typeparam>
    public class OrmConfig<Tadapter, Tentity>
        where Tadapter : IDbAdapter<Tadapter>
        //where Tschema : class
    {
        /// <summary>
        /// 实例化泛型数据库配置类
        /// </summary>
        public OrmConfig() {
        }

        static OrmConfig() {
            OrmConfig<Tadapter, Tentity>.Init(OrmConfig.My);

            OrmConfig<Tadapter, Tentity>.I =
                DataManager.I<Tadapter, Tentity>(OrmConfig<Tadapter, Tentity>.Fields, OrmConfig.My.debug);
            OrmConfig<Tadapter, Tentity>.Q =
                DataManager.Q<Tadapter, Tentity>(OrmConfig<Tadapter, Tentity>.Fields, OrmConfig.My.debug);
        }

        /// <summary>
        /// 数据表字段
        /// </summary>
        public static readonly List<Class<Tentity>.Property> Fields = new List<Class<Tentity>.Property>();
        /// <summary>
        /// 数据表主键字段
        /// </summary>
        public static readonly List<Class<Tentity>.Property> Keys = new List<Class<Tentity>.Property>();
        /// <summary>
        /// 除主键意外的数据表字段
        /// </summary>
        public static readonly List<Class<Tentity>.Property> Values = new List<Class<Tentity>.Property>();
        /// <summary>
        /// 数据表唯一键字段
        /// </summary>
        public static readonly Dictionary<string, List<Class<Tentity>.Property>> Uniques = new Dictionary<string, List<Class<Tentity>.Property>>();

        /// <summary>
        /// 属性-字段映射集
        /// </summary>
        static Dictionary<string, MapAttribute> Maps = new Dictionary<string, MapAttribute>();

        /// <summary>
        /// 依据唯一键名获取唯一键组
        /// </summary>
        /// <param name="unique_name">唯一键名</param>
        /// <returns>指定唯一键名对应的唯一键组</returns>
        public static List<Class<Tentity>.Property> GetUniques(string unique_name) {
            if(OrmConfig<Tadapter, Tentity>.Uniques.ContainsKey(unique_name)) {
                return OrmConfig<Tadapter, Tentity>.Uniques[unique_name];
            } else {
                return null;
            }
        }

        /// <summary>
        /// 获取实体类对应的属性-字段映射集
        /// </summary>
        /// <returns>属性-字段映射集</returns>
        public static List<MapAttribute> GetMap() {
            List<MapAttribute> maps = new List<MapAttribute>();
            foreach(KeyValuePair<string, MapAttribute> kv in OrmConfig<Tadapter, Tentity>.Maps) {
                maps.Add(kv.Value);
            }
            return maps;
        }

        /// <summary>
        /// 获取指定属性字段映射
        /// </summary>
        /// <param name="p">指定属性</param>
        /// <returns>字段映射</returns>
        public static MapAttribute GetMap(Class<Tentity>.Property p) {
            string propName = p.Name;

            Dictionary<string, MapAttribute> maps = OrmConfig<Tadapter, Tentity>.Maps;
            if(maps.ContainsKey(propName)) {
                return maps[propName];
            }

            return null;
        }

        static readonly Exec<Tentity, DbCommand> I;
        /// <summary>
        /// 获取实体类插入代理
        /// </summary>
        /// <param name="P">实体类属性</param>
        /// <returns>插入代理</returns>
        public static Exec<Tentity, DbCommand> Get_I(IList<Class<Tentity>.Property> P) {
            if(P == OrmConfig<Tadapter, Tentity>.Fields || P == null || P.Count == 0) {
                return OrmConfig<Tadapter, Tentity>.I;
            }

            return DataManager.I<Tadapter, Tentity>(P);
        }

        static readonly Exec<DbDataReader, Tentity> Q;
        /// <summary>
        /// 获取实体类查询代理
        /// </summary>
        /// <param name="P">实体类属性</param>
        /// <returns>查询代理</returns>
        public static Exec<DbDataReader, Tentity> Get_Q(IList<Class<Tentity>.Property> P) {
            if(P == OrmConfig<Tadapter, Tentity>.Fields || P == null || P.Count == 0) {
                return OrmConfig<Tadapter, Tentity>.Q;
            }

            return DataManager.Q<Tadapter, Tentity>(P);
        }

        #region BASE

        /// <summary>
        /// 初始化实体类映射
        /// </summary>
        /// <param name="config">ORM配置档</param>
        static void Init(OrmConfig config) {
            Class<Tentity>.Property[] P = Class<Tentity>.GetMap();

            for(int i = 0, len = P.Length; i < len; i++) {
                Class<Tentity>.Property p_i = P[i];

                Type p_Type = p_i.IsNullable ? p_i.pTypeNull : p_i.pType;
                if(!p_i.IsPrimitive) {
                    continue;
                }

                MapAttribute map = OrmConfig<Tadapter,Tentity>.getMergedMap(config, p_i.Name,
                    OrmConfig<Tadapter>.getDefaultMap(p_Type), //数据库适配器默认映射
                    config.getGlobalMap<Tadapter, Tentity>(p_i), //用户配置文件全局映射
                    OrmConfig<Tadapter,Tentity>.getAttributeMap(p_i), //用户代码特性类型映射
                    config.getEntityMap<Tadapter, Tentity>(p_i) //用户配置文件实体类映射
                    );

                if(map == null) {
                    if(!p_i.IsEnum) {
                        throw new OrmException("数据库[{0}], 实体类[{1}], 属性[{2}], 未找到映射", Class<Tadapter>.Name, Class<Tentity>.FullName, p_i.Name);
                    } else {
                        Type enumBaseType = Enum.GetUnderlyingType(p_Type);
                        map = OrmConfig<Tadapter>.getDefaultMap(enumBaseType);
                        if(map == null) {
                            throw new OrmException("数据库[{0}], 实体类[{1}], 属性[{2}], 未找到映射", Class<Tadapter>.Name, Class<Tentity>.FullName, p_i.Name);
                        }

                        map.Name = p_i.Name;
                    }
                }

                if(map.IsIgnored) {
                    continue;
                }
                if(string.IsNullOrEmpty(map.SQL_TYPE)) {
                    throw new OrmException("数据库[{0}], 实体类[{1}], 属性[{2}], SQL_TYPE不可空", Class<Tadapter>.Name, Class<Tentity>.FullName, p_i.Name);
                }
                if(map.DbType == null) {
                    throw new OrmException("数据库[{0}], 实体类[{1}], 属性[{2}], DbType不可空", Class<Tadapter>.Name, Class<Tentity>.FullName, p_i.Name);
                }

                if(string.IsNullOrEmpty(map.Alias)) {
                    map.Alias = map.Name;
                }
                if(map.Name != map.Alias) {
                    map.name_alias = map.Alias + " As " + map.Name;
                } else {
                    map.name_alias = map.Name;
                }

                //Maps
                OrmConfig<Tadapter, Tentity>.Maps.Add(p_i.Name, map);

                //Fields
                OrmConfig<Tadapter, Tentity>.Fields.Add(p_i);

                if(map.IsPrimary) {
                    //Keys
                    OrmConfig<Tadapter, Tentity>.Keys.Add(p_i);
                } else {
                    //Values
                    OrmConfig<Tadapter, Tentity>.Values.Add(p_i);
                }

                //Uniques
                if(!string.IsNullOrEmpty(map.UniqueName)) {
                    if(!OrmConfig<Tadapter, Tentity>.Uniques.ContainsKey(map.UniqueName)) {
                        OrmConfig<Tadapter, Tentity>.Uniques.Add(map.UniqueName, new List<Class<Tentity>.Property>());
                    }
                    OrmConfig<Tadapter, Tentity>.Uniques[map.UniqueName].Add(p_i);
                }
            }
        }

        static MapAttribute getMergedMap(OrmConfig config, string map_name, params OrmConfig.Map[] maps) {
            MapAttribute map = null;

            for(int i = 0, len = maps.Length; i < len; i++) {
                OrmConfig.Map map_i = maps[i];
                if(map_i == null) {
                    continue;
                }
                if(map == null) {
                    map = new MapAttribute() { Name = map_name };
                }

                if(!string.IsNullOrEmpty(map_i.Alias)) {
                    map.Alias = map_i.Alias;
                }
                if(map_i.IsPrimary != null) {
                    map.IsPrimary = map_i.IsPrimary.Value;
                }
                if(!string.IsNullOrEmpty(map_i.UniqueName)) {
                    map.UniqueName = map_i.UniqueName;
                }
                if(map_i.IsNullable != null) {
                    map.IsNullable = map_i.IsNullable.Value;
                }
                if(map_i.IsIgnored != null) {
                    map.IsIgnored = map_i.IsIgnored.Value;
                }
                if(map_i.TrimString != null) {
                    map.TrimString = map_i.TrimString.Value;
                }
                if(!string.IsNullOrEmpty(map_i.SQL_TYPE)) {
                    map.SQL_TYPE = map_i.SQL_TYPE;
                }
                if(map_i.DbType != null) {
                    map.DbType = map_i.DbType.Value;
                }

                if(map_i.Conv != null) {
                    map.Conv =  
                        map_i.Conv is string ? config.Converters[map_i.Conv as string] : map_i.Conv as Type;
                }
            }

            return map;
        }
        /// <summary>
        /// 获取用户代码特性类型映射（在代码中通过MapAttribute特性指定实体类型映射）
        /// </summary>
        /// <param name="p">属性</param>
        /// <returns>类型映射</returns>
        public static OrmConfig.Map getAttributeMap(Property p) {
            MapAttribute[] M = Reflect.GetAttribute<MapAttribute>(p.This);
            if(M.Length > 0) {
                MapAttribute m = M[0]; m.Name = p.Name;
                return m;
            } else {
                return null;
            }
        }
        #endregion BASE
    }
}
